// Custom Class for Paladins Healing in a PVP environment, like BG or Arena
// Inspired by the wonderfull Sm0k3d's EndGame Pally HealBot CC
// Many thanks to him and to all the other developers!
// Created by Gilderoy

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using Styx;
using Styx.Combat.CombatRoutine;
using Styx.Helpers;
using Styx.Logic;
using Styx.Logic.Combat;
using Styx.Logic.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;

namespace RestorationIce
{
    partial class RestoIce : CombatRoutine
    {
        #region Combat
        private void ArenaCombat()
        {
            tank = PVPGetTank();
            checkthetank();
            if (unitcheck(tank) < 0)
            {
                slog(Color.DarkRed, "Ok, I'm lost, I thought we found a tank, instead I did not, CC is in Pause, please report this Error with full LOG!");
                return;
            }
            //if (tank == null) { tank = Me; }
            //if (!tank.IsValid) { return; }
            //mtank = PVPgetmtank();
            Enemy = PVPGiveEnemy(29);
            if (PVP_wanna_target && unitcheck(Enemy)>0 && (Me.CurrentTarget == null || !Me.CurrentTarget.IsValid || Me.CurrentTarget.Dead))
            {
                if (unitcheck(Enemy)>0)
                {
                    Enemy.Target();
                }
                else if (unitcheck(tank.CurrentTarget)>0)
                {
                    tank.CurrentTarget.Target();
                }
            }
            /*
            if (Enemy != null)
            {
                Enemy.Target();
            }
            else if (tank!=null && tank.CurrentTarget != null)
            {
                tank.CurrentTarget.Target();
                Enemy = tank.CurrentTarget;
            }*/
            if (PVPInterrupt() || StyxWoW.GlobalCooldown) { return; }
            else if (NeedtoRest()) { slog("resting"); return; }
            else if (Self()) { return; }           
            else if (PVP_want_urgent_removecorruption && PVPRemoveCorruptionNow()) { return; }
            //else if (Enemy != null && Me.Combat && EnemyInterrupt(PVP_wanna_rebuke, PVP_wanna_HoJ, ARENA_wanna_move_to_HoJ)) { return; }
            else if (PVPHealing(ARENA_wanna_move_to_heal)) { return; }
            else if (ManaRec(PVP_min_Innervate_mana)) { return; }
            else if (PVP_want_removecorruption && (Me.Combat || !Me.Mounted) && RemovingCorruption()) { return; }
            else if (Enemy != null && Me.Combat && Dps(PVP_wanna_DPS)) { return; }
            else if (TopOff()) { return; }
            else if (Enemy != null && Me.Combat && ConsumeTime(PVP_wanna_DPS)) { return; }
            else if (PVP_wanna_buff && Buff(ARENA_wanna_move_to_heal)) { return; }
            else if (PVP_wanna_mount && MountUp()) { return; }
            else
            {

            }
            return;
        }
        private void WorldPVPCombat()
        {
            BattlegroundCombat();
            return;
        }
        private void BattlegroundCombat()
        {
            tank = PVPGetTank();
            checkthetank();
            if (unitcheck(tank) < 0)
            {
                slog(Color.DarkRed, "Ok, I'm lost, I thought we found a tank, instead I did not, CC is in Pause, please report this Error with full LOG!");
                return;
            }
            //if (tank == null) { tank = Me; }
            //if (!tank.IsValid) { return; }
            if (PVP_wanna_target && unitcheck(Enemy) > 0 && (Me.CurrentTarget == null || !Me.CurrentTarget.IsValid || Me.CurrentTarget.Dead))
            {
                if (unitcheck(Enemy) > 0)
                {
                    Enemy.Target();
                }
                else if (unitcheck(tank.CurrentTarget) > 0)
                {
                    tank.CurrentTarget.Target();
                }
            }
            /*
            if (Enemy != null)
            {
                Enemy.Target();
            }
            else if (tank.CurrentTarget != null)
            {
                tank.CurrentTarget.Target();
                Enemy = tank.CurrentTarget;
            }*/
            if (PVPInterrupt() || StyxWoW.GlobalCooldown) { return; }
            else if (NeedtoRest()) { slog("resting"); return; }
            else if (Self()) { return; }            
            else if (PVP_want_urgent_removecorruption && PVPRemoveCorruptionNow()) { return; }            
            else if (PVPHealing(PVP_wanna_move_to_heal)) { return; }
            else if (ManaRec(PVP_min_Innervate_mana)) { return; }
            else if (PVP_want_removecorruption && (Me.Combat || !Me.Mounted) && RemovingCorruption()) { return; }
            else if (Enemy != null && Me.Combat && Dps(PVP_wanna_DPS)) { return; }
            else if (TopOff()) { return; }
            else if (Enemy != null && Me.Combat && ConsumeTime(PVP_wanna_DPS)) { return; }
            else if (PVP_wanna_buff && Buff(PVP_wanna_move_to_heal)) { return; }
            else if (PVP_wanna_mount && MountUp()) { return; }
            else
            {

            }
            return;
        }

        #endregion

        #region Action

        private bool PVPRemoveCorruptionNow()
        {            
            /*
            if (PVP_wanna_HoF)
            {
                foreach (WoWPlayer d in Me.PartyMembers)
                {
                    if (d.MovementInfo.RunSpeed < PVP_min_run_to_HoF && CanCast("Hand of Freedom", d) && d.Combat && d.Distance<30)
                    {
                        Cast("Hand of Freedom", d, 30, "OhShit", "Target is slowed or snared, speed " + d.MovementInfo.RunSpeed.ToString());
                        //slog(Color.Violet, "Hand of Freedom on {0}", d.Name);
                    }
                }
            }
             */
            WoWPlayer p = PVPGetUrgentRemoveCorruptionTarget();
            //slog(Color.Violet, "Urgent RemovingCorruption {0}", p.Name);
            return Cast("Remove Corruption", p, 40, "Remove Corruption", "Need Urgent Dispell");
        }



        private WoWPlayer PVPGetTank()
        {/*
            if (tank == null)
            {
                if (RaFHelper.Leader != null)
                {
                    slog("rapid tank=leader");
                    tank = RaFHelper.Leader;
                }else if (Me != null)
                {
                    slog("rapid tank=Me");
                    tank = Me;
                }
            }*/
            if (combatfrom.Elapsed.TotalSeconds > 2)
            {
                if (tank != null && Me != null && tank.IsValid && Me.IsValid && !tank.Dead && !Me.Dead)
                {
                    if (Me.HealthPercent <
                        (tank.HealthPercent - 20) && CanCast("Hand of Salvation"))
                    {
                        slog(Color.Black, "Changing Tank to Me couse they are beating on me!");
                        return Me;
                    }
                    else if (RaFHelper.Leader != null)
                    {
                        if (tank != null && tank == Me && RaFHelper.Leader != null && RaFHelper.Leader != Me) { slog(Color.Black, "Changing Tank back to real tank!"); } else if (RaFHelper.Leader != null && tank != null && RaFHelper.Leader != tank) { slog(Color.Black, "Import the tank from LazyRaider!"); }
                        return RaFHelper.Leader;
                    }
                }
                combatfrom.Reset();
                combatfrom.Start();
            }
            else if (RaFHelper.Leader != null)
            {
                if (tank != null && tank == Me && RaFHelper.Leader != null && RaFHelper.Leader != Me) { slog(Color.Black, "Changing Tank back to real tank!"); } else if (RaFHelper.Leader != null && tank != null && RaFHelper.Leader != tank) { slog(Color.Black, "Import the tank from LazyRaider!"); }
                return RaFHelper.Leader;
            }
            else if (InRaid())
            {
                foreach (WoWPlayer p in Me.RaidMembers)
                {
                    if (IsTank(p))
                    {
                        return p;
                    }
                }
            }
            else
            {
                foreach (WoWPlayer p in Me.PartyMembers)
                {
                    if (IsTank(p))
                    {
                        return p;
                    }
                }
            }
            return null;
        }

        private bool PVPHealing(bool should_move)
        {
            if (tar != null && tank != null && tar.IsValid && tank.IsValid && !tar.Dead)
            {
                if (should_move && (tar.Distance > 30 || !tar.InLineOfSight)) { slog("Healing target is too far away or not in LOS, moving to them!"); MoveTo(tar); return true; }
                if (Me.Combat && !combatfrom.IsRunning) { combatfrom.Start(); noncombatfrom.Reset(); } else if (!Me.Combat) { combatfrom.Reset(); noncombatfrom.Start(); }
                if (!Me.Combat) { noncombatfrom.Start(); }
                String s = null;
                double hp = tar.HealthPercent;
                if (Me.Mounted && !Me.Combat && !tank.Combat) { return false; }
                if (!Me.Combat && !tar.Combat && tar.Distance > 40) { return false; }


                if (hp > 60) { goto jump; }
                //=============================================================================================================================================================================                
                if (hp < NS_HT && !GotBuff("Nature's Swiftness") && CanCast("Nature's Swiftness")) { ChainSpells(tar.Name, "Nature's Swiftness", "Healing Touch"); }
                else if (hp < NG_HT && !GotBuff("Nature's Grace") && CanCast("Regrowth", tar) && !(Me.IsMoving) && (!(ng.ElapsedMilliseconds < 45000) || (ng.ElapsedMilliseconds == 0))) { s = "Regrowth"; ng.Reset(); ng.Start(); return Cast(s, tar, 40, "Heal", "Regrowth!"); }
                else if (hp < NG_HT && GotBuff("Nature's Grace") && CanCast("Healing Touch", tar) && !(Me.IsMoving)) { s = "Healing Touch"; isinterrumpable = true; return Cast(s, tar, 40, "Heal", "Healing Touch while Nature's Grace is up!"); }
                //Tree of Life
                else if ((hp < TREEIT) && ShouldAoe(Tree_num, TREEIT) && ShouldTree(Tree_num)) { s = "Tree of Life"; return Cast(s, tar, 40, "Heal", "Got Wood?, I do!"); }
                else if (GotBuff("Tree of Life") && CanCast("Wild Growth")) { tar = Clusters.GetBestUnitForCluster(Unit.NearbyFriendlyPlayers, ClusterType.Radius, 30f); s = "Wild Growth"; return Cast(s, tar, 40, "Heal", "Smart Wild Growth!"); }
                else if (Tranqtree == true && GotBuff("Tree of Life") && CanCast("Tranquility") && !(Me.IsMoving)) { s = "Tranquility"; isinterrumpable = false; return Cast(s, tar, 40, "Heal", "AoE Tranq? "); }
                //End Tree of Life
                else if ((hp < Tranq) && ShouldAoe(Tranq_num, Tranq) && ShouldTranquility(Tranq_num)) { s = "Tranquility"; isinterrumpable = false; return Cast(s, tar, 40, "Heal", "Savaing the world with a tranq!"); }
                else if (hp < NGHT_PostAOE && GotBuff("Nature's Grace") && CanCast("Healing Touch", tar) && !(Me.IsMoving)) { s = "Healing Touch"; isinterrumpable = true; return Cast(s, tar, 40, "Heal", "AoE Checks over now Healing Touch Go!"); }
            jump:
                if (hp < CC_HT && GotBuff("Clearcast") && CanCast("Healing Touch", tar) && !(Me.IsMoving)) { s = "Healing Touch"; isinterrumpable = true; return Cast(s, tar, 40, "Heal", "Free Healing Touch Woot!"); }
                else if (hp < CC_RG && GotBuff("Clearcast") && CanCast("Regrowth", tar) && !(Me.IsMoving)) { s = "Regrowth"; isinterrumpable = true; return Cast(s, tar, 40, "Heal", "O.o Free Regrowth, gee Thanks!"); }
                //Tank HoT's                
                else if (hp < Tank_HT && tar.Guid == tank.Guid && CanCast("Healing Touch") && !Me.IsMoving) { s = "Healing Touch"; isinterrumpable = true; return Cast(s, tar, 40, "Heal", "Nub tank needs another heal dam him!"); }
                else if (tar.Guid == tank.Guid && CanCast("Lifebloom") && !GotBuff("Lifebloom", tar)) { s = "Lifebloom"; return Cast(s, tar, 40, "Heal", "Tank's missing lifebloom, ... again..., casting it again..."); }
                else if (tar.Guid == tank.Guid && CanCast("Lifebloom") && GotBuff("Lifebloom", tar) && tar.ActiveAuras["Lifebloom"].StackCount < 3 && tar.Auras["Lifebloom"].CreatorGuid == Me.Guid) { s = "Lifebloom"; return Cast(s, tar, 40, "Heal", "Tank'missing the triple threat, giving him some more lifeboom now!"); }
                else if (tar.Guid == tank.Guid && CanCast("Lifebloom") && GotBuff("Lifebloom", tar) && tar.ActiveAuras["Lifebloom"].TimeLeft.TotalMilliseconds <= 1500 && hp > 40 && tar.Auras["Lifebloom"].CreatorGuid == Me.Guid) { s = "Lifebloom"; return Cast(s, tar, 40, "Heal", "Refreashing the Tank's Lifeboom before he drops.. tick tick tick...!"); }
                else if (hp < Tank_Rejuv && tar.Guid == tank.Guid && CanCast("Rejuvenation", tar) && !GotBuff("Rejuvenation", tar)) { s = "Rejuvenation"; return Cast(s, tar, 40, "Heal", "Tank's getting tired hears a rejuvenation..."); }
                //End of Tank HoT's
                else if (hp < SM && CanCast("Rejuvenation", tar) && (GotBuff("Rejuvenation", tar) || GotBuff("Regrowth", tar))) { s = "Swiftmend"; return Cast(s, tar, 40, "Heal", "Swiftmend, for the instant heal!"); }
                else if ((hp < WG_min_hp) && ShouldAoe(WG_Num, WG_min_hp) && ShouldWildGrowth(WG_Num) && CanCast("Wild Growth", tar)) { tar = Clusters.GetBestUnitForCluster(Unit.NearbyFriendlyPlayers, ClusterType.Radius, 30f); s = "Wild Growth"; return Cast(s, tar, 40, "Heal", "Smart Wild Growth Again!"); }
                else if ((hp < Efflo_min_hp) && ShouldAoe(Efflo_Num, Efflo_min_hp) && ShouldEfflorescence(Efflo_Num) && CanCast("Swiftmend", tar)) { tar = Clusters.GetBestUnitForCluster(Unit.NearbyFriendlyPlayers, ClusterType.Radius, 8f); s = "Swiftmend"; return Cast(s, tar, 40, "Heal", "Oooo. can even do smart Efflorescece!"); }
                else if (hp < Rejuv && CanCast("Rejuvenation", tar) && !GotBuff("Rejuvenation", tar)) { s = "Rejuvenation"; return Cast(s, tar, 40, "Heal", "Rejuv the slacker"); }
                else if (hp < HT && CanCast("Healing Touch", tar) && !(Me.IsMoving)) { s = "Healing Touch"; isinterrumpable = true; return Cast(s, tar, 40, "Heal", "Healing Touch.. Again...!"); }
                else if (hp < Nourish && CanCast("Nourish", tar) && (GotBuff("Rejuvenation", tar) || GotBuff("Regrowth", tar) || GotBuff("Wild Growth", tar) || GotBuff("Lifebloom", tar))) { s = "Nourish"; isinterrumpable = true; return Cast(s, tar, 40, "Heal", "Nourish for the noobish Hottie!"); }
                //=============================================================================================================================================================================
                
                return false;

            }
            else
            {
                return false;
            }
        }



        #endregion

        #region Helpers
        
        /*
        private WoWUnit PVPGiveEnemy(int distance)
        {
            WoWUnit enemy = (from unit in ObjectManager.GetObjectsOfType<WoWUnit>(false, false)
                             orderby unit.HealthPercent ascending
                             //where unit.IsHostile                                                         PVE
                             //where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember)      //  PVP e si potrebbe anche togliere
                             where !unit.Dead
                             where tank.CurrentTargetGuid == unit.Guid
                             //where tank.CurrentTargetGuid == unit.Guid
                             where unit.Distance < distance
                             where unit.InLineOfSight
                             
                             select unit
                             
                            ).FirstOrDefault();
            if (enemy != null) { slog(Color.Black, "Enemy {0}", enemy.Name); }
            return enemy;
        }*/
        private WoWPlayer PVPGiveEnemy(int distance)
        {
            
            WoWPlayer enemy = (from unit in ObjectManager.GetObjectsOfType<WoWPlayer>(true,false)
                             //where unit.IsHostile                                                         
                             orderby unit.HealthPercent ascending
                             //where (unit.IsTargetingMyPartyMember || unit.IsTargetingMyRaidMember)      //  PVP e si potrebbe anche togliere
                             where !unit.IsInMyPartyOrRaid
                             where !unit.Dead
                             //where tank.CurrentTargetGuid == unit.Guid
                             where unit.Distance < distance
                             where unit.InLineOfSight
                             where !unit.IsPet
                             select unit
                            ).FirstOrDefault();
          //  if (enemy != null) { slog(Color.Black, "Enemy {0}", enemy.Name); }
            return enemy;
        }


        private bool PVPInterrupt()
        {
            if (Me.IsCasting && (lastCast != null && !lastCast.Dead && lastCast.HealthPercent >= PVP_do_not_heal_above) && isinterrumpable)
            {
                SpellManager.StopCasting();
                if (lastCast != null) { slog(Color.Brown, "Interrupting Healing, target at {0} %", Round(lastCast.HealthPercent)); }
                isinterrumpable = false;
                lastCast = null;
                return true;
            }
            else if (Me.IsCasting)
            {

                return true;
            }
            else
            {
                return false;
            }
        }


        private bool PVPOhShitButton()
        {
            if (((!GotBuff("Barkskin") && CanCast("Barksin"))))
            {
                slog("Pressing OH SHIT buttons!");
                ChainSpells("Barkskin");
                return true;
            }
            return false;
        }

        private void ChainSpells(params string[] spells)
        {
            string macro = "";
            foreach (string s in spells)
            {
                macro += "CastSpellByName(\"" + s + "\", true);";
            }
            Lua.DoString(macro);
        }
      
        private void ChainSpells(string target, params string[] spells)
        {
            string macro = "";
            foreach (string s in spells)
            {
                macro += "CastSpellByName(\"" + s + "\", " + target + ");";
            }
            Lua.DoString(macro);
        }
        private void ChainNSspell(string target, params string[] spells)
        {
            string macro = "";
            macro += "CastSpellByName(Nature's Swiftness, 1);";
            foreach (string s in spells)
            {
                macro += "CastSpellByName(\"" + s + "\", " + target + ");";
            }
            Lua.DoString(macro);
        }
        private WoWPlayer PVPGetUrgentRemoveCorruptionTarget()
        {
            return (from unit in ObjectManager.GetObjectsOfType<WoWPlayer>(true, true)
                    orderby unit.HealthPercent ascending
                    where !unit.Dead
                    where !unit.IsGhost
                    where unit.Distance < 80
                    where (unit.IsInMyPartyOrRaid || unit.IsMe)
                    where PVPNeedsUrgentRemoveCorruption(unit)
                    select unit).FirstOrDefault();
        }
       
        private bool PVPNeedsUrgentRemoveCorruption(WoWPlayer p)
        {
            foreach (WoWAura a in p.ActiveAuras.Values)
            {
                if ((a.IsHarmful) &&
                    (!p.ActiveAuras.ContainsKey("Unstable Affliction")) &&
                    ((p.ActiveAuras.ContainsKey("Fear")) ||
                    (p.ActiveAuras.ContainsKey("Polymorph")) ||
                    (p.ActiveAuras.ContainsKey("Freezing Trap")) ||
                    (p.ActiveAuras.ContainsKey("Wyvern Sting")) ||
                    (p.ActiveAuras.ContainsKey("Seduction")) ||
                    (p.ActiveAuras.ContainsKey("Mind Control")) ||
                    //(p.ActiveAuras.ContainsKey("Entangling Roots")) ||
                    //(p.ActiveAuras.ContainsKey("Frost Nova")) ||
                    //(p.ActiveAuras.ContainsKey("Chains of Icey")) ||
                    (p.ActiveAuras.ContainsKey("Repentance")) ||
                    (p.ActiveAuras.ContainsKey("Hex")) ||
                    (p.ActiveAuras.ContainsKey("Psychic Scream")) ||
                    (p.ActiveAuras.ContainsKey("Hammer of Justice")) ||
                    (p.ActiveAuras.ContainsKey("Intimidating Shout")) ||
                    (p.ActiveAuras.ContainsKey("Howl of Terror"))
                )){
                    WoWDispelType t = a.Spell.DispelType;
                    if (t == WoWDispelType.Curse || t == WoWDispelType.Magic || t == WoWDispelType.Poison)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        #endregion
    }   
}
